//Element的集合,但不仅仅是数组
var Elements = new Native({

 initialize: function(elements, options){
  //可选参数,提供默认值
  options = $extend({ddup: true, cash: true}, options);
  //又见双竖线,默认值的优雅方式
  elements = elements || [];

  /*
  这两个参数根据拼写看不出来含意,看后面的代码
  ddup应该是标识集合是否不重复
  cash应该是标识是否对子项进行Element扩展
  */
  if (options.ddup || options.cash){
   var uniques = {}, returned = [];
   for (var i = 0, l = elements.length; i < l; i++){
    /*
    对子项进行Element扩展
    $.element的第二形参名为nocash,因此这里取反
    */
    var el = $.element(elements[i], !options.cash);
    //如果要求集合没有重复项
    if (options.ddup){
     //根据Element的uid来判断,如果uniques[el.uid]为true说明已经存在
     if (uniques[el.uid]) continue;
     uniques[el.uid] = true;
    }
    returned.push(el);
   }
   elements = returned;
  }
  //如果要求扩展,返回Elements对象,否则返回elements数组(当然也有可能已经是Elements的)
  return (options.cash) ? $extend(elements, this) : elements;
 }

});


Elements.implement({

 //根据标签名过滤集合中的项
 filter: function(filter, bind){
  if (!filter) return this;
  return new Elements(Array.filter(this, (typeof filter == 'string') ? function(item){
   return item.match(filter);
  } : filter, bind));
 }

});

/*
这个方法非常有用,配合Element类的afterImplement,使得所有Element的方法能同时应用于Elements
比如element.addEvent('click', clickHandler)和elements.addEvent('click' clickHandler);
*/
Elements.multi = function(property){
 //返回一个闭包,主要为了延后执行
 return function(){
  var items = [];
  var elements = true;
  for (var i = 0, j = this.length; i < j; i++){
   //执行子项的同名方法,并传送同样的参数,让开发者感觉不到Element和Elements的差异
   var returns = this[i][property].apply(this[i], arguments);
   items.push(returns);
   //确保子项的方法中返回的是子项本身
   if (elements) elements = ($type(returns) == 'element');
  }
  //如果方法返回子项本身,则仍将数组扩展为Elements返回,否则只返回数组
  return (elements) ? new Elements(items) : items;
 };
};